package neptune.web.server.services;

import it.robertobifulco.ias.IncorrectParamsException;
import it.robertobifulco.ias.Operation;
import it.robertobifulco.ias.UnauthorizedOperationException;
import it.robertobifulco.ias.principalmanager.Principal;
import it.robertobifulco.ias.rolemanager.RoleUndefinedException;

import java.util.ArrayList;

import javax.servlet.http.HttpSession;

import neptune.manager.storage.VmTemplateRepository;
import neptune.web.client.model.ApplicationGenericInfo;
import neptune.web.client.model.SerializableVmTemplate;
import neptune.web.client.services.ApplicationGenericService;
import neptune.web.client.services.SecurityException;
import neptune.web.server.ApplicationManager;
import neptune.web.server.Debug;
import neptune.web.server.operations.OpenRandomSSHRedirectPort;
import neptune.web.server.operations.UsersInfo;
import neptune.web.server.security.SecurityHelper;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class ApplicationGenericServiceImpl extends RemoteServiceServlet
		implements ApplicationGenericService {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5435159738212790853L;

	public ApplicationGenericInfo getApplicationInfo()
			throws SecurityException, Exception {
		try {
			// Recupera la sessione utente e l'operazione
			HttpSession session = getThreadLocalRequest().getSession(false);
			UsersInfo operation = (UsersInfo) SecurityHelper.getOperation(
					UsersInfo.ID, session);

			// Popola l'oggetto con i dati sugli utenti
			ApplicationGenericInfo info = (ApplicationGenericInfo) (operation
					.execute(null))[0];

			Principal user = SecurityHelper.getPrincipal(session);
			boolean isAdmin = false;
			if (user.getRole().equals("System Admin"))
				isAdmin = true;

			/*
			 * Numero di esperimenti in cui e' coinvolto un utente. Il system
			 * admin e' coinvolto in tutti gli esperimemnti del sistema. La
			 * seguente operazione non e' gestita tramite IAS poiche' contiene
			 * intrinsecamente un controllo sull'utente che la sta eseguendo.
			 * Infatti, per ricavare il numero di esperimenti in cui l'utente e'
			 * coinvolto, e' necessario passare anche il nomeutente stesso
			 * all'operazione. Tale nomeutente e' recuperato dalla sessione
			 * gestita dal server e quindi non e' falsificabile.
			 */
			int experimentsNumber = ApplicationManager.getApplicationManager()
					.getNeptuneManager().getExperimentsRepository()
					.getExperimentNumberForUser(user.getId(), isAdmin);

			info.setExperimentsNumber(experimentsNumber);

			info.setActualUserRole(user.getRole());

			VmTemplateRepository vmTempRep = ApplicationManager
					.getApplicationManager().getNeptuneManager()
					.getVmTemplateRepository();
			ArrayList<SerializableVmTemplate> vmTmps = new ArrayList<SerializableVmTemplate>(
					0);

			String[] vmTmpNames = vmTempRep.getVmTemplateNames();
			for (String tmpName : vmTmpNames) {
				vmTmps.add(SerializationHelper
						.toSerializableVmTemplate(vmTempRep
								.getVmTemplateByName(tmpName)));
			}

			info.setVmTemplates(vmTmps);

			return info;
		} catch (UnauthorizedOperationException e) {
			e.printStackTrace();
			throw new SecurityException(e.getMessage());
		} catch (RoleUndefinedException e) {
			e.printStackTrace();
			throw new SecurityException(e.getMessage());
		} catch (IncorrectParamsException e) {
			e.printStackTrace();
			throw new SecurityException(e.getMessage());
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception(e.getMessage());
		}
	}

	public String openRandomSSHRedirectPort(String ipServer)
			throws SecurityException, Exception {
		try {
			HttpSession session = getThreadLocalRequest().getSession(false);
			Operation operation = SecurityHelper.getOperation(
					OpenRandomSSHRedirectPort.ID, session);
			Object[] obj = operation.execute(new Object[] { ipServer });
			return (String) obj[0];
		} catch (SecurityException e) {
			throw new SecurityException(e.getMessage());
		} catch (Exception e) {
			Debug.printTrace(e);
			throw new Exception(e);
		}
	}
}
